#!groovy
//
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
build_and_test = '''
mkdir -p ${ERLANG_VERSION}
cd ${ERLANG_VERSION}
rm -rf build
mkdir build
cd build
tar -xf ${WORKSPACE}/apache-couchdb-*.tar.gz
cd apache-couchdb-*
./configure --with-nouveau --with-clouseau --js-engine=${JS_ENGINE}
make check || (make build-report && false)
'''

docs_changed = "git diff --name-only origin/${env.CHANGE_TARGET} | grep -q '^src/docs/'"
other_changes = "git diff --name-only origin/${env.CHANGE_TARGET} | grep -q -v '^src/docs/'"

pipeline {

  // no top-level agent; agents must be declared for each stage
  agent none

  environment {
    recipient = 'notifications@couchdb.apache.org'
    // Following fix an issue with git <= 2.6.5 where no committer
    // name or email are present for reflog, required for git clone
    GIT_COMMITTER_NAME = 'Jenkins User'
    GIT_COMMITTER_EMAIL = 'couchdb@apache.org'
    // Parameters for the matrix build
    DOCKER_IMAGE_BASE = 'apache/couchdbci-debian:bookworm-erlang'
    // https://github.com/jenkins-infra/jenkins.io/blob/master/Jenkinsfile#64
    // We need the jenkins user mapped inside of the image
    // npm config cache below deals with /home/jenkins not mapping correctly
    // inside the image
    DOCKER_ARGS = '-e npm_config_cache=/home/jenkins/.npm -e HOME=. -e MIX_HOME=/home/jenkins/.mix -e HEX_HOME=/home/jenkins/.hex -e PIP_CACHE_DIR=/home/jenkins/.cache/pip -v=/etc/passwd:/etc/passwd -v /etc/group:/etc/group -v /home/jenkins/.gradle:/home/jenkins/.gradle:rw,z -v /home/jenkins/.hex:/home/jenkins/.hex:rw,z -v /home/jenkins/.npm:/home/jenkins/.npm:rw,z -v /home/jenkins/.cache/pip:/home/jenkins/.cache/pip:rw,z -v /home/jenkins/.mix:/home/jenkins/.mix:rw,z'

    // *** BE SURE TO ALSO CHANGE THE ERLANG VERSIONS FARTHER DOWN ***
    // Search for ERLANG_VERSION
    // see https://issues.jenkins.io/browse/JENKINS-61047 for why this cannot
    // be done parametrically
    LOW_ERLANG_VER = '25.3.2.13'
  }

  options {
    buildDiscarder(logRotator(numToKeepStr: '10', artifactNumToKeepStr: '10'))
    // This fails the build immediately if any parallel step fails
    parallelsAlwaysFailFast()
    preserveStashes(buildCount: 10)
    timeout(time: 3, unit: 'HOURS')
    timestamps()
  }

  stages {

    stage('Setup Env') {
      agent {
        docker {
          image "${DOCKER_IMAGE_BASE}-${LOW_ERLANG_VER}"
          label 'docker'
          args "${DOCKER_ARGS}"
          registryUrl 'https://docker.io/'
          registryCredentialsId 'dockerhub_creds'
        }
      }
      options {
        timeout(time: 10, unit: 'MINUTES')
      }
      steps {
        script {
          env.DOCS_CHANGED = '0'
          env.ONLY_DOCS_CHANGED = '0'
          if ( sh(returnStatus: true, script: docs_changed) == 0 ) {
            env.DOCS_CHANGED = '1'
            if (sh(returnStatus: true, script: other_changes) == 1) {
              env.ONLY_DOCS_CHANGED = '1'
            }
          }
        }
      }
      post {
        cleanup {
          // UGH see https://issues.jenkins-ci.org/browse/JENKINS-41894
          sh 'rm -rf ${WORKSPACE}/*'
        }
      }
    } // stage 'Setup Environment'

    stage('Docs Check') {
      // Run docs `make check` stage if any docs changed
      when {
        beforeOptions true
        expression { DOCS_CHANGED == '1' }
      }
      agent {
        docker {
          image "${DOCKER_IMAGE_BASE}-${LOW_ERLANG_VER}"
          label 'docker'
          args "${DOCKER_ARGS}"
          registryUrl 'https://docker.io/'
          registryCredentialsId 'dockerhub_creds'
        }
      }
      options {
        timeout(time: 15, unit: 'MINUTES')
      }
      steps {
        sh '''
          make python-black
        '''
        sh '''
          (cd src/docs && make check)
        '''
      }
      post {
        cleanup {
          // UGH see https://issues.jenkins-ci.org/browse/JENKINS-41894
          sh 'rm -rf ${WORKSPACE}/*'
        }
      }
    } // stage Docs Check

    stage('Build Docs') {
      // Build docs separately if only docs changed. If there are other changes, docs are
      // already built as part of `make dist`
      when {
        beforeOptions true
        expression { ONLY_DOCS_CHANGED == '1' }
      }
      agent {
        docker {
          image "${DOCKER_IMAGE_BASE}-${LOW_ERLANG_VER}"
          label 'docker'
          args "${DOCKER_ARGS}"
          registryUrl 'https://docker.io/'
          registryCredentialsId 'dockerhub_creds'
        }
      }
      options {
        timeout(time: 30, unit: 'MINUTES')
      }
      steps {
        sh '''
           (cd src/docs && ./setup.sh ; make html)
         '''
      }
      post {
        cleanup {
          // UGH see https://issues.jenkins-ci.org/browse/JENKINS-41894
          sh 'rm -rf ${WORKSPACE}/*'
        }
      }
    } // stage Build Docs

    stage('Source Format Checks') {
      when {
        beforeOptions true
        expression { ONLY_DOCS_CHANGED == '0' }
      }
      agent {
        docker {
          image "${DOCKER_IMAGE_BASE}-${LOW_ERLANG_VER}"
          label 'docker'
          args "${DOCKER_ARGS}"
          registryUrl 'https://docker.io/'
          registryCredentialsId 'dockerhub_creds'
        }
      }
      options {
        timeout(time: 15, unit: "MINUTES")
      }
      steps {
        sh '''
          rm -rf apache-couchdb-*
          ./configure --skip-deps --spidermonkey-version 78
          make erlfmt-check
          make elixir-source-checks
          make python-black
        '''
      }
      post {
        cleanup {
          // UGH see https://issues.jenkins-ci.org/browse/JENKINS-41894
          sh 'rm -rf ${WORKSPACE}/*'
        }
      }
    } // stage Erlfmt


    stage('Make Dist') {
      when {
        beforeOptions true
        expression { ONLY_DOCS_CHANGED == '0' }
      }
      agent {
        docker {
          image "${DOCKER_IMAGE_BASE}-${LOW_ERLANG_VER}"
          label 'docker'
          args "${DOCKER_ARGS}"
          registryUrl 'https://docker.io/'
          registryCredentialsId 'dockerhub_creds'
        }
      }
      options {
        timeout(time: 15, unit: "MINUTES")
      }
      steps {
        sh '''
          rm -rf apache-couchdb-*
          ./configure --spidermonkey-version 78 --with-nouveau --with-clouseau
          make dist
          chmod -R a+w * .
        '''
      }
      post {
        success {
          stash includes: 'apache-couchdb-*.tar.gz', name: 'tarball'
        }
        cleanup {
          // UGH see https://issues.jenkins-ci.org/browse/JENKINS-41894
          sh 'rm -rf ${WORKSPACE}/*'
        }
      }
    } // stage Make Dist

    // TODO Rework once Improved Docker Pipeline Engine is released
    // https://issues.jenkins-ci.org/browse/JENKINS-47962
    // https://issues.jenkins-ci.org/browse/JENKINS-48050

    stage('Make Check') {
      when {
        beforeOptions true
        expression { ONLY_DOCS_CHANGED == '0' }
      }
      matrix {
        axes {
          axis {
            name 'ERLANG_VERSION'
            values '25.3.2.13', '26.2.5.2'
          }
          axis {
            name 'SM_VSN'
            values '78'
          }
          axis {
            name 'JS_ENGINE'
            values 'quickjs', 'spidermonkey'
          }
        }

        stages {
          stage('Build and Test') {
            agent {
              docker {
                image "${DOCKER_IMAGE_BASE}-${ERLANG_VERSION}"
                label 'docker'
                args "${DOCKER_ARGS}"
              }
            }
            options {
              skipDefaultCheckout()
              timeout(time: 90, unit: "MINUTES")
            }
            steps {
              unstash 'tarball'
              sh( script: build_and_test )
            }
            post {
              always {
                junit '**/.eunit/*.xml, **/_build/*/lib/couchdbtest/*.xml, **/src/mango/nosetests.xml, **/test/javascript/junit.xml'
              }
              cleanup {
                sh 'rm -rf ${WORKSPACE}/*'
              }
            }
          } // stage
        } // stages
      } // matrix
    } // stage "Make Check"
  } // stages
} // pipeline
